package com.sf.fy.uav.applet.login.controller;

import com.sf.fy.uav.applet.login.service.LoginService;
import com.sf.fy.uav.applet.utils.RandomUtils;
import com.sf.fy.uav.common.enums.ServicePrefixEnum;
import com.sf.fy.uav.common.response.login.LoginResponse;
import com.sf.fy.uav.common.response.operational.RegisterResponse;
import com.sf.fy.uav.common.utils.PhoneEncoderUtil;
import com.sf.fy.uav.common.utils.RedisPrefixKey;
import com.sf.fy.uav.common.utils.Rs;
import com.sf.fy.uav.sms.rest.SendSmsRest;
import io.swagger.annotations.Api;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.validation.constraints.Size;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Calendar;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * @author LTQ
 * 登录
 */
@Api(tags = "登录")
@RestController
@RequestMapping("/home/")
@Validated
public class LoginController {

    private final static Logger logger = LoggerFactory.getLogger(LoginController.class);

    @Autowired
    private LoginService loginService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private SendSmsRest sendSmsRest;

    @Value("${sms.a-minute-limit: 1}")
    private Integer aMinuteLimit;



    @Value("${sms.half-an-hour-limit: 10}")
    private Integer halfAnHourLimit;

    @Value("${sms.a-day-limit: 20}")
    private Integer aDayLimit;


    @GetMapping("get-code")
    @Operation(tags = "获取验证码", description = "获取验证码")
    public Rs<String> getCode(@RequestParam @Size(min = 11, max = 11) String phoneNumber) {
        phoneNumber = phoneNumber.trim();
        boolean is11Digits = Pattern.matches("\\d{11}", phoneNumber);
        if (!is11Digits) {
            return Rs.error("手机号格式不正确");
        }
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - 1);
        Long aMinuteAgo = calendar.getTimeInMillis();
        Set<String> set = redisTemplate.opsForZSet().rangeByScore(ServicePrefixEnum.MONTHLY_SETTLEMENT_PLATFORM + RedisPrefixKey.APPLET_PHONE_CODE_COUNT_DOWN + phoneNumber, aMinuteAgo, System.currentTimeMillis());
        if (set.size() >= aMinuteLimit) {
            throw new RuntimeException("一分钟内只能获取1次");
        }
        calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - 30);
        Long thirtyMinuteAgo = calendar.getTimeInMillis();
        set = redisTemplate.opsForZSet().rangeByScore(ServicePrefixEnum.MONTHLY_SETTLEMENT_PLATFORM + RedisPrefixKey.APPLET_PHONE_CODE_COUNT_DOWN + phoneNumber, thirtyMinuteAgo, System.currentTimeMillis());
        if (set.size() >= halfAnHourLimit) {
            throw new RuntimeException("半小时内只能获取10次");
        }
        calendar.set(Calendar.MINUTE, calendar.get(Calendar.DAY_OF_MONTH) - 1);
        Long aDayAgo = calendar.getTimeInMillis();
        set = redisTemplate.opsForZSet().rangeByScore(ServicePrefixEnum.MONTHLY_SETTLEMENT_PLATFORM + RedisPrefixKey.APPLET_PHONE_CODE_COUNT_DOWN + phoneNumber, aDayAgo, System.currentTimeMillis());
        if (set.size() >= aDayLimit) {
            throw new RuntimeException("一天内只能获取20次");
        }
        String code = RandomUtils.getStringRandom();
        sendSmsRest.sendSms(phoneNumber, code);
        redisTemplate.opsForZSet().add(ServicePrefixEnum.MONTHLY_SETTLEMENT_PLATFORM + RedisPrefixKey.APPLET_PHONE_CODE_COUNT_DOWN + phoneNumber, code, System.currentTimeMillis() + 0);
        redisTemplate.opsForValue().set(ServicePrefixEnum.MONTHLY_SETTLEMENT_PLATFORM + RedisPrefixKey.APPLET_PHONE_CODE + phoneNumber, code);
        return Rs.success();
    }

    @Operation(tags = "通过验证码登录", description = "通过验证码登录")
    @GetMapping("login-by-code")
    public Rs<LoginResponse> loginByCode(@RequestParam @Size(min = 11, max = 11) String phoneNumber, @RequestParam @Size(min = 6, max = 6) String code) {
        LoginResponse loginResponse = loginService.loginByPhoneNumber(phoneNumber, code);
        return Rs.success(loginResponse);
    }

    @Operation(tags = "注册", description = "注册")
    @GetMapping("register")
    public Rs<RegisterResponse> register(@RequestParam @Size(min = 11, max = 11) String phoneNumber, @RequestParam @Size(min = 6, max = 6) String code) {
        Boolean checkCode = loginService.checkCode(code, phoneNumber);
        if (!checkCode) {
            return Rs.failed("验证失败");
        }
        String token = loginService.register(phoneNumber);
        RegisterResponse registerResponse = new RegisterResponse();
        registerResponse.setToken(token);
        registerResponse.setPhoneNumber(PhoneEncoderUtil.desensitization(phoneNumber));
        return Rs.success(registerResponse);
    }
}
